/*
 * *****************************************************************************
 *  Copyright ( c ) 2019 huibur Inc. All Rights Reserved.
 *
 *  This software is the confidential and proprietary information of Huibur Inc
 *  (*Confidential Information*). You shall not disclose such Confidential Information
 *  and shall use it only in accordance with the terms of the license agreement
 *  you entered into with Huibur or a Huibur authorized
 *  reseller (the "License Agreement*).
 *  ******************************************************************************
 */

package com.huibur.devicecheck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huibur.devicecheck.config.ChannelType;
import com.huibur.devicecheck.config.ClientType;
import com.huibur.devicecheck.constant.Constants;
import com.huibur.devicecheck.enums.RoleEnums;
import com.huibur.devicecheck.enums.UserEnums;
import com.huibur.devicecheck.exception.UserDisableException;
import com.huibur.devicecheck.exception.UserInfoExistException;
import com.huibur.devicecheck.exception.UserNotFoundException;
import com.huibur.devicecheck.exception.UserNotPasswordException;
import com.huibur.devicecheck.mapper.UserMapper;
import com.huibur.devicecheck.model.param.LoginParam;
import com.huibur.devicecheck.model.param.UserParam;
import com.huibur.devicecheck.model.po.UserPO;
import com.huibur.devicecheck.model.query.PwdQuery;
import com.huibur.devicecheck.model.query.UserQuery;
import com.huibur.devicecheck.model.vo.UserVO;
import com.huibur.devicecheck.request.ObjRes;
import com.huibur.devicecheck.request.PageRes;
import com.huibur.devicecheck.request.SessionContext;
import com.huibur.devicecheck.service.IUserService;
import com.huibur.devicecheck.session.JwtTools;
import com.huibur.devicecheck.session.UserSubject;
import com.huibur.devicecheck.utils.ConvertPageUtil;
import com.huibur.devicecheck.utils.DateUtils;
import com.huibur.devicecheck.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/*******************************************************
* Title: UserServiceImpl.java
* Description:
* @author baiqingshuo
* @date 2021/9/24
* @version 1.0
*******************************************************/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements IUserService {

    @Autowired
    UserMapper userMapper;

    /**
     * 登录
     * @param loginParam
     * @return
     */
    @Override
    public ObjRes<UserVO> login(LoginParam loginParam) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getMobile, loginParam.getMobile())
                .ne(UserPO::getStatus, UserEnums.DELETE.getCode())
                .eq(UserPO::getRole,RoleEnums.ADMIN.getCode()));
                //后台管理系统管理员登录
        if (null == userPO) {
            throw new UserNotFoundException();
        } else if (userPO.getStatus().equals(UserEnums.NORMAL.getCode())) {
            //用户存在，将密码进行MD5加密，与数据库进行碰撞
            String pwd = MD5Util.getMD5String(loginParam.getPassword());
            if (!pwd.equals(userPO.getPassword())) {
                throw new UserNotPasswordException();
            }
        } else if (userPO.getStatus().equals(UserEnums.DISABLE.getCode())) {
            throw new UserDisableException();
        }

        UserVO userVO = new UserVO();
        userVO.setAdminId(userPO.getAdminId());
        userVO.setRole(Long.valueOf(userPO.getRole()));
        userVO.setMobile(userPO.getMobile());
        userVO.setName(userPO.getName());
        userVO.setStatus(userPO.getStatus());
        userVO.setCreateAt(userPO.getCreateAt());

        // 生成token
        UserSubject userSubject = new UserSubject();
        userSubject.setChannelType(ChannelType.WEB);
        userSubject.setClientType(ClientType.MANAGER);
        userSubject.setLoginDateTime(System.currentTimeMillis());
        userSubject.setName(userPO.getName());
        userSubject.setUserId(userPO.getAdminId());
        String token = JwtTools.generatorJwt(userSubject);
        userSubject.setToken(token);
        SessionContext.setUserSubject(userSubject);

        userVO.setToken(token);

        return new ObjRes<UserVO>().data(userVO);
    }

    /**
     * 新增用户
     * @param userParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> insert(UserParam userParam) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getMobile, userParam.getMobile())
                .ne(UserPO::getStatus, UserEnums.DELETE.getCode()));

        if (null != userPO) {
            throw new UserInfoExistException();
        }

        UserPO user = new UserPO();
        user.setRole(userParam.getRole());
        user.setMobile(userParam.getMobile());
        user.setPassword(MD5Util.getMD5String(Constants.PASSWORD));
        user.setName(userParam.getName());
        user.setStatus(UserEnums.NORMAL.getCode());
        user.setCreateAt(DateUtils.getCurrentTimestamp());
        user.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
        userMapper.insert(user);
        return new ObjRes<Void>().success("创建成功");
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        UserPO userPO = new UserPO();
        userPO.setAdminId(id);
        userPO.setStatus(UserEnums.DELETE.getCode());
        userMapper.updateById(userPO);
        return true;
    }

    /**
     * 编辑用户
     * @param adminId
     * @param userParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> updateUser(Long adminId, UserParam userParam) {
        UserPO user = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .ne(UserPO::getAdminId, adminId)
                .eq(UserPO::getMobile, userParam.getMobile())
                .ne(UserPO::getStatus, UserEnums.DELETE.getCode())
                .eq(UserPO::getRole,RoleEnums.ADMIN.getCode()));
        if (null != user) {
            throw new UserInfoExistException();
        }
        UserPO userPO = new UserPO();
        userPO.setRole(userParam.getRole());
        userPO.setMobile(userParam.getMobile());
        userPO.setName(userParam.getName());
        userPO.setStatus(UserEnums.NORMAL.getCode());
        userPO.setUpdateAt(DateUtils.getCurrentTimestamp());
        userPO.setUpdateBy(SessionContext.getCurrentUserSubject().getUserId());
        userMapper.update(userPO,new LambdaQueryWrapper<UserPO>().eq(UserPO::getAdminId,adminId));
        return new ObjRes<Void>().success("修改成功");
    }

    /**
     * 用户列表(查询并分页)
     * @param userQuery
     * @return
     */
    @Override
    public PageRes<UserVO> selectListUser(UserQuery userQuery) {
        Page<UserPO> page = new Page<>(userQuery.getCurrent(), userQuery.getPageSize());
        IPage<UserVO> pages = userMapper.selectListUser(page,userQuery);
        return ConvertPageUtil.convertPage(userQuery.getCurrent(),page.getTotal(),pages.getRecords());
    }

    /**
     * 获取用户详情
     * @param id
     * @return
     */
    @Override
    public UserVO selectUserById(Long id) {
        UserPO userPO = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getAdminId, id));
        UserVO userVO = new UserVO();
        userVO.setAdminId(userPO.getAdminId());
        userVO.setRole(Long.valueOf(userPO.getRole()));
        userVO.setName(userPO.getName());
        userVO.setMobile(userPO.getMobile());
        userVO.setStatus(userPO.getStatus());
        userVO.setCreateAt(userPO.getCreateAt());
        return userVO;
    }

    /**
     * 重置密码
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean resetPwd(Long id) {
        UserPO userPO = new UserPO();
        userPO.setAdminId(id);
        userPO.setPassword(MD5Util.getMD5String(Constants.PASSWORD));
        userMapper.updateById(userPO);
        return true;
    }

    /**
     * 修改密码
     * @param pwdQuery
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> updatePwd(PwdQuery pwdQuery) {
        UserPO userPo = userMapper.selectOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getAdminId, pwdQuery.getAdminId()));
        if (SessionContext.getCurrentUserSubject().getUserId().equals(userPo.getAdminId())) {
            String MD5OldPwd = MD5Util.getMD5String(pwdQuery.getNewPwd());
            String md5String = MD5Util.getMD5String(pwdQuery.getOldPwd());
            if (!userPo.getPassword().equals(md5String)) {
                return new ObjRes<Void>().error("旧密码输入错误，请重新输入");
            }
            if (userPo.getPassword().equals(MD5OldPwd)) {
                return new ObjRes<Void>().error("新密码不能与旧密码相同");
            } else {
                userPo.setPassword(MD5Util.getMD5String(pwdQuery.getNewPwd()));
                userMapper.updateById(userPo);
                return new ObjRes<Void>().success("修改成功");
            }
        } else {
            return new ObjRes<Void>().error("不能修改他人用户");
        }
    }

    /**
     * 分配时只获取巡检员
     * @return
     */
    @Override
    public List<UserVO> selectCheckRole() {
        List<UserVO> userVOList = new ArrayList<>();
        List<UserPO> userPOList = userMapper.selectList(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getRole, RoleEnums.CHECK.getCode())
                .eq(UserPO::getStatus, UserEnums.NORMAL.getCode()));
        for (UserPO userPO : userPOList) {
            UserVO userVO = new UserVO();
            userVO.setAdminId(userPO.getAdminId());
            userVO.setName(userPO.getName());
            userVO.setRole(Long.valueOf(userPO.getRole()));
            userVO.setMobile(userPO.getMobile());
            userVO.setStatus(userPO.getStatus());
            userVO.setCreateAt(userPO.getCreateAt());
            userVOList.add(userVO);
        }
        return userVOList;
    }
}


